home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 301-325 / disk_315 / surf / readilbm.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  9KB  |  398 lines

  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include "readilbm.h"
  4.  
  5. #define FALSE 0
  6. #define TRUE 1
  7.  
  8. #define RED 0
  9. #define GRN 1
  10. #define BLU 2
  11.  
  12.  /* color to grey conversion methods */
  13.  
  14. #define AVERAGE 0
  15. #define LUMIN    1
  16. #define DIST     2
  17. #define REDONLY  3
  18. #define GREENONLY 4
  19. #define BLUEONLY 5
  20.  
  21. #define MakeID(a,b,c,d) ( ((a)<<24) | ((b)<<16) | ((c)<<8) | (d) )
  22.  
  23. #define ID_FORM MakeID('F','O','R','M')
  24. #define ID_ILBM MakeID('I','L','B','M')
  25. #define ID_BMHD MakeID('B','M','H','D')
  26. #define ID_CMAP MakeID('C','M','A','P')
  27. #define ID_CAMG MakeID('C','A','M','G')
  28. #define ID_BODY MakeID('B','O','D','Y')
  29.  
  30. #define ROUNDUP(x) ( ((x)+1) & (~1L) )
  31.  
  32.  
  33.  
  34. static struct CHUNK {
  35.     unsigned long Id, Size;
  36. } Chunk;
  37.  
  38. static unsigned char   cmap[32][3];
  39.  
  40. struct BMHD {
  41.     short w,h,x,y;
  42.     char npl,mask,compress,pad1;
  43.     short transparentColor;
  44.     char xAspect,yAspect;
  45.     short pageWidth,pageHeight;
  46. };
  47.  
  48.  
  49. static short    Color[32],              /* output colors        */
  50.                 Method = AVERAGE;       /* color conversion     */
  51. static short     numcolors;
  52.  
  53. static
  54. FILE            *fin;                   /* input file           */
  55.  
  56. extern char     *malloc();
  57.  
  58. static void FRead();
  59. static void ReadBMHD();
  60. static void ReadChunk();
  61. static void RastOut();
  62. static void HamOut();
  63. static char GetIlbmVal();
  64. static void InitColorMappings();
  65. static short Convert();
  66. static void ReadDecomLine();
  67. static void ProcessRows();
  68.  
  69. #define ABORT(str) { OutErr(str); goto ErrorExit; }
  70.  
  71.  
  72. void SetGreyModel( model )
  73.     int model;
  74. {
  75.     Method = model;
  76. }
  77.  
  78.  /*
  79.   * main routine for reading in an iff file
  80.   */
  81.  
  82. void ReadIlbm(filename)
  83.     char *filename;
  84. {
  85.     struct BMHD bmhd;
  86.     long    ILBMid;
  87.     unsigned char cmapFlag = FALSE,
  88.                   bmhdFlag = FALSE;
  89.  
  90.  
  91.     if ((fin = fopen (filename, "r")) == NULL) {
  92.         OutErr ("ERROR: cannot open input file");
  93.         return;
  94.     }
  95.     /* read in iff file */
  96.  
  97.     ReadChunk ();
  98.     if (Chunk.Id != ID_FORM)
  99.         ABORT ("Not an IFF File");
  100.  
  101.     FRead (&ILBMid, 4);
  102.     if (ILBMid != ID_ILBM)
  103.         ABORT ("Not an ILBM File");
  104.  
  105.     while (1) {
  106.         long camgdata;
  107.  
  108.         ReadChunk ();
  109.  
  110.         if (Chunk.Id == ID_BODY)
  111.             break;
  112.  
  113.         if( feof( fin ) ) {
  114.             ABORT("reached end of file without seeing body\n");
  115.         }
  116.  
  117.         switch (Chunk.Id) {
  118.             case ID_CMAP:
  119.                 FRead (cmap, Chunk.Size);
  120.                 numcolors = Chunk.Size/3;
  121.                 cmapFlag = TRUE;
  122.                 break;
  123.             case ID_BMHD:
  124.                 ReadBMHD (&bmhd);
  125.                 bmhdFlag = TRUE;
  126.                 break;
  127.             case ID_CAMG:
  128.                 FRead( &camgdata, sizeof(camgdata) );
  129.                 break;
  130.             default:            /* unknown identifier */
  131.                 fseek( fin, Chunk.Size, 1);
  132.                 break;
  133.         }
  134.     }
  135.     if (!cmapFlag) {
  136.         ABORT("IFF file does not contain a CMAP chunk before the BODY\n");
  137.     }
  138.  
  139.     if (!bmhdFlag) {
  140.         ABORT("IFF file does not contain a BMHD chunk before the BODY\n");
  141.     }
  142.  
  143.     InitColorMappings();
  144.     if( OpenImgPix( bmhd.w, bmhd.h, Convert(0xf, 0xf, 0xf)) ) {
  145.         ProcessRows(&bmhd);
  146.     }
  147.  
  148.     ErrorExit:
  149.         fclose( fin);
  150. }
  151.  
  152. static void ProcessRows(bmhd)
  153.     struct BMHD *bmhd;
  154. {
  155.     char *rastlist[6];
  156.     char *Raster;
  157.     int depth, i, v, pixwidth;
  158.     int BytePerLine;
  159.  
  160.     depth = bmhd->npl;
  161.     pixwidth = bmhd->w;
  162.     BytePerLine =(pixwidth+7) / 8;
  163.  
  164.  
  165.     Raster = (char *) malloc (BytePerLine * depth);
  166.  
  167.     if(!Raster ) {
  168.         OutErr("ProcessRows:could not allocate Raster");
  169.         return;
  170.     }
  171.  
  172.     for( i = 0; i < depth; i++ ) {
  173.         rastlist[i] = Raster + BytePerLine*i;
  174.     }
  175.  
  176.     for( v = 0; v < bmhd->h; v++) {
  177.         switch (bmhd->compress) {
  178.             case 0:
  179.                 FRead (Raster, BytePerLine * depth);
  180.                 break;
  181.             case 1:
  182.                 for( i = 0; i < depth; i++) {
  183.                     ReadDecomLine( BytePerLine, rastlist[i]);
  184.                 }
  185.                 break;
  186.             default:
  187.                 ABORT ("Unknown Compression type in BODY");
  188.  
  189.         }
  190.         if(depth == 6 ) {
  191.             HamOut( rastlist, pixwidth, v);
  192.         }
  193.         else {
  194.             RastOut( rastlist, pixwidth, v, depth);
  195.         }
  196.     }
  197.  
  198.     ErrorExit:
  199.         if( Raster ) free(Raster);
  200. }
  201.  
  202.  
  203. static void ReadDecomLine(linebytes, rp)
  204.     int linebytes;
  205.     char *rp;
  206. {
  207.     int runlen;
  208.     char pixel;
  209.  
  210.     while (linebytes) {
  211.         runlen = getc (fin);
  212.         if (runlen > 127)
  213.             runlen -= 256;
  214.         if (runlen >= 0) {
  215.             runlen++;
  216.             FRead (rp, runlen);
  217.             rp += runlen;
  218.             linebytes -= runlen;
  219.         }
  220.         else {
  221.             runlen = -runlen + 1;
  222.             linebytes -= runlen;
  223.             pixel = getc (fin);
  224.             do
  225.                 *(rp++) = pixel;
  226.             while (--runlen);
  227.         }
  228.     }
  229. }
  230.  
  231.  /*
  232.   * Convert - convert (r,g,b) to hex greyscale.
  233.   */
  234.  
  235. static short Convert(r,g,b)
  236.     unsigned char   r,g,b;
  237. {
  238.     short   i,
  239.             rd, gd, bd,
  240.             min,
  241.             dist,
  242.             best;
  243.  
  244.  /* convert color according to 'Method' */
  245.     switch (Method) {
  246.         case AVERAGE:           /* average r,g,b to obtain grey level */
  247.             return ((short)((r + g + b) / 3));
  248.         case LUMIN:             /* use NTSC luminescence as grey level */
  249.             return ((short)((r * 30 + g * 59 + b * 11) / 100));
  250.         case DIST:          /* use grey with minimum distance in color */
  251.             min = 15*15 * 3;
  252.             for( i = 0; i < numcolors; i++ ) {
  253.                 rd = r -i;
  254.                 gd = g - i;
  255.                 bd = b - i;
  256.                 dist = rd * rd + gd * gd + bd * bd;
  257.                 if( dist < min ) {
  258.                     min = dist; best = i;
  259.                 }
  260.             }
  261.             return( best );
  262.         case REDONLY:
  263.             return((short)r);
  264.         case GREENONLY:
  265.             return((short)g);
  266.         case BLUEONLY:
  267.             return((short)b);
  268.         default:
  269.             exit(-1); /* error, big one */
  270.     }
  271. }                               /* Convert */
  272.  
  273. static void InitColorMappings()
  274. {
  275.     int     i;
  276.  
  277.  /* put colors in 4-bit range and Convert */
  278.     for (i = 0; i < 32; i++) {
  279.         cmap[i][RED] >>= 4;
  280.         cmap[i][GRN] >>= 4;
  281.         cmap[i][BLU] >>= 4;
  282.         Color[i] = Convert (cmap[i][RED], cmap[i][GRN], cmap[i][BLU]);
  283.     }
  284. }
  285.  
  286.  
  287. /*
  288.  * leftmost pixel of byte is in most significant bit of byte
  289.  */
  290. static char GetIlbmVal( rastlist, h, bpp )
  291.     char *rastlist[6];
  292.     int h, bpp;
  293. {
  294.     int i;
  295.     char value = 0;
  296.     short mask, bytep;
  297.  
  298.     mask = 0x80 >> ( h & 7);
  299.     bytep = h >> 3;
  300.  
  301.     for( i = bpp-1; i >= 0; i-- ) {
  302.         value <<= 1;
  303.         value |= (*(rastlist[i]+bytep) & mask) ? 1: 0;
  304.     }
  305.     return( value );
  306. }
  307.  
  308.  /*
  309.   * HamOut - output ham image in hex.
  310.   */
  311. static void HamOut(rastlist, pixwidth, v)
  312.     char *rastlist[6];
  313.     int pixwidth, v;
  314. {
  315.     unsigned char   lastred = 0,
  316.                     lastgreen = 0,
  317.                     lastblue = 0;
  318.     int     h;
  319.     char pixval;
  320.     for( h = 0; h <pixwidth; h++ ) {
  321.         short shade;
  322.  
  323.         shade = GetIlbmVal(rastlist, h, 6);
  324.         pixval = shade & 0x0F;
  325.         switch (shade & 0x30) {
  326.         case 0x00:
  327.             lastred = cmap[pixval][RED];
  328.             lastgreen = cmap[pixval][GRN];
  329.             lastblue = cmap[pixval][BLU];
  330.             shade = Color[pixval];
  331.             break;
  332.         case 0x10:
  333.             lastblue = pixval;
  334.             shade = Convert(lastred,lastgreen,lastblue);
  335.             break;
  336.         case 0x20:
  337.             lastred = pixval;
  338.             shade = Convert(lastred,lastgreen,lastblue);
  339.             break;
  340.         case 0x30:
  341.             lastgreen = pixval;
  342.             shade = Convert(lastred,lastgreen,lastblue);
  343.         }
  344.         SetImgPix(h, v, shade);
  345.     }
  346. }
  347.  
  348.  /*
  349.   * RastOut - handle normal bit mapped images
  350.   */
  351. static void RastOut(rastlist, pixwidth, v, depth)
  352.     char *rastlist[6];
  353.     int pixwidth, v, depth;
  354. {
  355.     int h;
  356.     for( h = 0; h < pixwidth; h++ ) {
  357.         short shade;
  358.         shade = Color[GetIlbmVal( rastlist, h, depth)];
  359.         SetImgPix( h, v, shade);
  360.     }
  361. }
  362.  
  363.  /*
  364.   * ReadChunk - read in an IFF Chunk.
  365.   */
  366.  
  367. static void ReadChunk()
  368. {
  369.     FRead (&Chunk, sizeof (Chunk));
  370.  
  371. }                               /* ReadChunk */
  372.  
  373.  /*
  374.   * ReadBMHD - read the BMHD structure.
  375.   */
  376.  
  377. static void ReadBMHD(bmhd)
  378. struct BMHD *bmhd;
  379. {
  380.     FRead (bmhd, Chunk.Size);
  381. }                               /* ReadBMHD */
  382.  
  383.  
  384.  /*
  385.   * FRead - read 'len' bytes to 'pointer' while checking for an error.
  386.   */
  387.  
  388. static void FRead(pointer,len)
  389. char    *pointer;
  390. int     len;
  391. {
  392.     if (fread (pointer, len, 1, fin) == 0)  {
  393.         char outbuff[90];
  394.         sprintf(outbuff,"Fread Error in reading input file at %d ", ftell(fin));
  395.         OutErr(outbuff);
  396.     }
  397. }                               /* FRead */
  398.